package com.tanhua.server.service;

import cn.hutool.core.collection.CollUtil;

import com.tanhua.autoconfig.template.OssTemplate;
import com.tanhua.commons.utils.Constants;
import com.tanhua.dubbo.api.MovementApi;
import com.tanhua.dubbo.api.UserInfoApi;
import com.tanhua.dubbo.api.VisitorsApi;
import com.tanhua.model.domain.UserInfo;
import com.tanhua.model.mongo.Movement;
import com.tanhua.model.mongo.Visitors;
import com.tanhua.model.vo.ErrorResult;
import com.tanhua.model.vo.MovementsVo;
import com.tanhua.model.vo.PageResult;
import com.tanhua.model.vo.VisitorsVo;
import com.tanhua.server.exception.BusinessException;
import com.tanhua.server.interceptor.UserHolder;
import org.apache.commons.lang.StringUtils;
import org.apache.dubbo.config.annotation.DubboReference;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.util.*;
import java.util.stream.Collectors;

@Service
public class MovementService {
    @DubboReference
    private MovementApi movementApi;
    @Autowired
    private OssTemplate ossTemplate;
    @DubboReference
    private UserInfoApi userInfoApi;
    @Autowired
    private RedisTemplate<String, String> redisTemplate;
    @DubboReference
    private VisitorsApi visitorsApi;

    @Autowired
    private MqMessageService mqMessageService;
    /**
     * 发布动态
     *
     * @param movement
     * @param multipartFiles
     * @throws IOException
     */
    public void publishMovement(Movement movement, MultipartFile[] multipartFiles) throws IOException {
        //判断动态是否为空
        if (StringUtils.isEmpty(movement.getTextContent())) {
            throw new BusinessException(ErrorResult.contentError());
        }
        //获取当前用户id
        Long userId = UserHolder.getUserId();
        //将文件上传到阿里云
        List<String> medias = new ArrayList<>();
        //遍历数组中的文件
        for (MultipartFile multipartFile : multipartFiles) {
            //调用文件上传方法，参数是文件名，输入流。获取文件url地址
            String upload = ossTemplate.upload(multipartFile.getOriginalFilename(), multipartFile.getInputStream());
            medias.add(upload);
        }
        //生成日志登录
        mqMessageService.sendLogMessage(UserHolder.getUserId(), "0201", "movement", null);
        //将数据封装到Movement对象中
        movement.setUserId(userId);
        movement.setMedias(medias);
        //调用Api发布动态,返回值动态id
        String movementId = movementApi.publish(movement);
        //审核动态
        mqMessageService.sendAudiMessage(movementId);

    }

    /**
     * 查询个人动态
     *
     * @param userId
     * @param page
     * @param pagesize
     * @return
     */
    public PageResult findByUserId(Long userId, Integer page, Integer pagesize) {
        //根据id查询分页中的个人所有动态信息
        PageResult pr = movementApi.findByUserId(userId, page, pagesize);
        //获取分页中的所有动态数据集合
        List<Movement> items = (List<Movement>) pr.getItems();
        //判断是否为空
        if (items == null) {
            //如果为null，直接返回分页页面
            return pr;
        }
        //通过api获取基本信息
        UserInfo userInfo = userInfoApi.findById(userId);
        //创建vo集合,用于装基本信息和个人所有动态数据
        List<MovementsVo> vos = new ArrayList<>();
        //不过不为空，将基本信息和动态信息整合成Vo类型的对象
        for (Movement item : items) {
            MovementsVo vo = MovementsVo.init(userInfo, item);
            String key = Constants.MOVEMENTS_INTERACT_KEY + item.getId().toHexString();
            String hashKey = Constants.MOVEMENT_LIKE_HASHKEY + UserHolder.getUserId();
            if (redisTemplate.opsForHash().hasKey(key, hashKey)) {
                vo.setHasLiked(1);
            }
            vos.add(vo);
        }
        //构建返回值
        pr.setItems(vos);
        return pr;
    }

    /**
     * 好友动态查询
     *
     * @param page
     * @param pagesize
     * @return
     */
    public PageResult findmovements(Integer page, Integer pagesize) {
        //从线程中获取id
        Long userId = UserHolder.getUserId();
        //根据id查询分页动态信息，从分页中查询动态集合
        List<Movement> list = movementApi.findmovements(userId, page, pagesize);
        return getPageResult(page, pagesize, list);
    }

    /**
     * 公共方法
     *
     * @param page
     * @param pagesize
     * @param list
     * @return
     */
    private PageResult getPageResult(Integer page, Integer pagesize, List<Movement> list) {
        //判断动态信息是否空
        if (CollUtil.isEmpty(list)) {
            return new PageResult();
        }
        //获取动态发布人的id列表
        List<Long> userIds = CollUtil.getFieldValues(list, "userId", Long.class);
        //通过用户id获取列表用户详情
        Map<Long, UserInfo> map = userInfoApi.findByIds(userIds, null);
        //构建Movement的vo对象
        List<MovementsVo> vos = new ArrayList<>();
        //遍历动态集合
        for (Movement movement : list) {
            //通过id获取基本信息
            UserInfo userInfo = map.get(movement.getUserId());
            //判断用户基本信息是否存在
            if (userInfo != null) {
                //构建vo对象
                MovementsVo vo = MovementsVo.init(userInfo, movement);
                //修复点赞状态的bug，判断hashkey是否存在
                String key = Constants.MOVEMENTS_INTERACT_KEY + movement.getId().toHexString();
                String hashKey = Constants.MOVEMENT_LIKE_HASHKEY + UserHolder.getUserId();
                if (redisTemplate.opsForHash().hasKey(key, hashKey)) {
                    vo.setHasLiked(1);
                }
                String hashKey1 = Constants.MOVEMENT_LOVE_HASHKEY + UserHolder.getUserId();
                if (redisTemplate.opsForHash().hasKey(key, hashKey1)) {
                    vo.setHasLoved(1);
                }
                vos.add(vo);
            }
        }
        //构建返回值
        return new PageResult(page, pagesize, 0, vos);
    }

    /**
     * 推荐好友
     *
     * @param page
     * @param pagesize
     * @return
     */
    public PageResult findRecommend(Integer page, Integer pagesize) {
        //从redis中获取主键key值 用户
        String redisKey = Constants.MOVEMENTS_RECOMMEND + UserHolder.getUserId();
        //通过key获取values值 推荐的数据
        String redisValues = (String) redisTemplate.opsForValue().get(redisKey);
        List<Movement> list = Collections.EMPTY_LIST;
        //判断推荐的数据是否为空
        if (StringUtils.isEmpty(redisValues)) {
            //如果没有推荐数据，就随机分配10条
            list = movementApi.randomMovements(pagesize);
        } else {
            //如果有数据。处理pid数据 先切割
            String[] values = redisValues.split(",");
            if ((page - 1) * pagesize < values.length) {
                List<Long> pids = Arrays.stream(values).skip((page - 1) * pagesize).limit(pagesize)
                        .map(e -> Long.valueOf(e))
                        .collect(Collectors.toList());
                list = movementApi.findmovementsById(pids);
            }
        }
        return getPageResult(page, pagesize, list);
    }

    /**
     * 单条动态查询
     *
     * @param movementId
     * @return
     */
    public MovementsVo findByid(String movementId) {
        mqMessageService.sendLogMessage(UserHolder.getUserId(),"0202", "movement", null);
        Movement movement = movementApi.findByid(movementId);
        if (movement != null) {
            UserInfo userInfo = userInfoApi.findById(movement.getUserId());
            return MovementsVo.init(userInfo, movement);
        } else {
            return null;
        }
    }

    /**
     * 访客查询
     *
     * @return
     */
    public List<VisitorsVo> visitors() {
        mqMessageService.sendLogMessage(UserHolder.getUserId(),"0208", "movement", null);
        //获取访问时间，从redis中获取主键key值
        String redisKey = Constants.VISITORS_USER;
        String hashKey = String.valueOf(UserHolder.getUserId());
        String value = (String) redisTemplate.opsForHash().get(redisKey, hashKey);
        Long date = StringUtils.isEmpty(value) ? null : Long.valueOf(value);

        //调用API查询列表,通过本地id根据时间获取访客
        List<Visitors> visitors = visitorsApi.queryVisitors(date, UserHolder.getUserId());
        //判断访客数据是否为空
        if (CollUtil.isEmpty(visitors)){
            return new ArrayList<>();
        }
        //获取所有访客的id
        List<Long> visitorUserId = CollUtil.getFieldValues(visitors, "visitorUserId", Long.class);
        //获取访客的详情
        Map<Long, UserInfo> map = userInfoApi.findByIds(visitorUserId,null);

        List<VisitorsVo> vos=new ArrayList<>();
        //构造vo ，遍历所有访客数据
        for (Visitors visitor : visitors) {
            //获取单个用户的详细信息
            UserInfo userInfo = map.get(visitor.getVisitorUserId());
            VisitorsVo vo = VisitorsVo.init(userInfo, visitor);
            vos.add(vo);
        }
        //返回值
        return vos;
    }
}
